	
	Ext.namespace("panel.widgets.positioner");
	
	panel.widgets.positioner = function(config) {
		
		var state  = {}; 
		var widget = {};
		
		/**
		 * Config:
		**/
		config            = Ext.value(config, {});
		config.dataIndex  = Ext.value(config.dataIndex, "position");
		config.titleIndex = Ext.value(config.titleIndex, "title");
		
		/**
		 * Observer: 
		**/
		
		widget.observer = new Ext.util.Observable();
		
		widget.observer.addEvents({
			
			"init"    : true,
			"refresh" : true,
			"move"    : true,
			"before_move" : true
			
		});
		
		$H(config.listeners).each( function(f, e) {
			
			widget.observer.on(e, f);
			
		});
		
		/**
		 * Column: 
		**/
		
		widget.column = { 
			
			id        : config.dataIndex,      
			header    : "#",       
			dataIndex : config.dataIndex,  
			width     : 35, 
			sortable  : true,
			align     : "center",
			renderer  : function(v, cell, record) {
				
				cell.css += " s_bold fnt_size_main ";
				return v;
					
			}
			
		};
		
		widget.dataIndex = config.dataIndex;
		
		/**
		 * Refresh
		**/
		
		widget.refresh = function() {
			
			panel.console.log("PW:positioner", "A", "REFRESH", ">>>");
			
			config.store.each( function(r, k) {
				
				r.data[config.dataIndex] = (k + 1);
				
			} );
			
			config.store.fireEvent("datachanged", config.store);
			
			widget.observer.fireEvent("refresh");
			
			panel.console.log("PW:positioner", "A", "REFRESH", "<<<");
			
		};
		
		config.store.on("filtered",      function() { widget.disable(); });
		config.store.on("filtercleared", function() { widget.enable(); });
		
		/**
		 * Grid D&D:
		**/
		widget.observer.on("init", function() {

			config.grid.getView().dragZone.scroll = true;
			
			config.grid.getDragDropText = Ext.value(config.getDragDropText, function() {

				return config.grid.getSelectionModel().getSelected().data[config.titleIndex];
				
			});

            var ddrow = new Ext.ux.grid.ReorderDropTarget(config.grid, {
                
				copy: false,
				
				listeners: {
					
					beforerowmove: function(me, oi, ni, records) {
						
						if( widget.observer.fireEvent("before_move", records) === false ) {
							return false; };
						
						return state.enabled;
						
					},
					
                    afterrowmove: function(me, oi, ni, records) {
                        
						widget.observer.fireEvent("move", records);
						widget.refresh();
						 
                    }
					
                }
            });
	
	        Ext.dd.ScrollManager.register( config.grid.getView().getEditorParent() );
			
		});
		
		/**
		 * Buttons:
		**/
		widget.buttons = {};
		
		widget.buttons.move_up = new Ext.Button({
			cls      : "x-btn-size-28 x-btn-icon",
			disabled : true,
			iconCls  : "icon_arrow_up",
			handler  : function() {
				
				if( !config.selection.hasSelection() ) {
					return; }
					
				var selected = config.selection.getSelections("selected");
				var records  = config.selection.getSelections();
				
				if( widget.observer.fireEvent("before_move", records) === false ) {
					return false; };
				
				try {
					
					records.each( function(record) {
						
						var index = config.store.indexOf(record);
					
						if( !index ) {
							throw "stop"; }
							
						config.store.remove(record);
						config.store.insert(index - 1, [record]);
						
					});
					
				} catch( e ) { if(e != "stop") { throw e; } }
				
				widget.refresh();
					
				if( selected.length ) {
					config.selection.setSelections(selected, true, "select"); }
				
				widget.observer.fireEvent("move", records);
								
			}
		});
				
		widget.buttons.move_down = new Ext.Button({
			cls      : "x-btn-size-28 x-btn-icon",
			disabled : true,
			iconCls  : "icon_arrow_down",
			handler  : function() {
				
				if( !config.selection.hasSelection() ) {
					return; }
					
				var selected = config.selection.getSelections("selected");
					
				var records  = config.selection.getSelections();
				
				if( widget.observer.fireEvent("before_move", records) === false ) {
					return false; };
					
				try {	
				
					var rrecords = [];
					
					records.each( function(record) {
						
						rrecords.unshift(record);
						
					});
				
					rrecords.each( function(record) {
						
						var index = config.store.indexOf(record);
					
						if( index == (config.store.getCount() - 1) ) {
							throw "stop"; }

						config.store.remove(record);
						config.store.insert(index + 1, [record]);
						
					});
					
				} catch( e ) { if(e != "stop") { throw e; } }
				
				widget.refresh();
				
				if( selected.length ) {
					config.selection.setSelections(selected, true, "select"); }
				
				widget.observer.fireEvent("move", records);

			}
		});
		
		widget.buttons.move_to_up = new Ext.Button({
			cls      : "x-btn-size-28 x-btn-icon",
			disabled : true,
			iconCls  : "icon_arrow_to_up",
			handler  : function() {
				
				if( !config.selection.hasSelection() ) {
					return; }
					
				var selected = config.selection.getSelections("selected");
					
				var records  = config.selection.getSelections();
				
				if( widget.observer.fireEvent("before_move", records) === false ) {
					return false; };
					
				records.each( function(record, index) {
						
					config.store.remove(record);
					config.store.insert(index, [record]);
					
				});
				
				widget.refresh();
				
				if( selected.length ) {
					config.selection.setSelections(selected, true, "select"); }
				
				widget.observer.fireEvent("move", records);
				
			}
		});
		
		widget.buttons.move_to_down = new Ext.Button({
			cls      : "x-btn-size-28 x-btn-icon",
			disabled : true,
			iconCls  : "icon_arrow_to_down",
			handler  : function() {
				
				if( !config.selection.hasSelection() ) {
					return; }
					
				var selected = config.selection.getSelections("selected");
					
				var records  = config.selection.getSelections();
				
				if( widget.observer.fireEvent("before_move", records) === false ) {
					return false; };
					
				records.each( function(record, index) {
					
					var index = (config.store.getCount() - 1) - index;
					
					config.store.remove(record);
					config.store.insert(index, [record]);
					
				});
				
				widget.refresh();
				
				if( selected.length ) {
					config.selection.setSelections(selected, true, "select"); }
				
				widget.observer.fireEvent("move", records);
				
			}
		});
		
		widget.observer.on("init", function() {
			
			var _fe = function() {
				
				panel.console.log("PW:positioner", "->E", "check buttons status");
				
				if( state.enabled && config.selection.hasSelection() ) {
					
					widget.buttons.move_up.enable();
					widget.buttons.move_down.enable();
					widget.buttons.move_to_up.enable();
					widget.buttons.move_to_down.enable();
					
				} else {
					
					widget.buttons.move_up.disable();
					widget.buttons.move_down.disable();
					widget.buttons.move_to_up.disable();
					widget.buttons.move_to_down.disable();
					
				}	// if
				
			}
			
			config.selection.observer.on("selection", _fe);
			widget.observer.on("move", _fe);
			
		});
		
		
		/**
		 * Init 
		**/
		
		widget.init = function() {
			
			/**
			 * 1. Do init.
			 * 2. Avoid reinitialization if defined 
			**/

			if( !state.init ) {
				
				panel.console.log("PW:positioner", "INIT");
				
				state.init    = true;
				state.enabled = true;
				
				if( config.grid instanceof Function ) {
					config.grid = config.grid(); }
				
				widget.observer.fireEvent("init", widget);
				
			}	// if
			
		};
		
		widget.disable = function() {
			
			state.enabled = false;
			
		};
		
		widget.enable = function() {
			
			state.enabled = true;
			
		};
		
		return widget;
		
	};